package net;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.xmlbeans.impl.util.HexBin;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.handler.codec.http.DefaultHttpRequest;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpMethod;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.HttpVersion;
import org.jboss.netty.util.CharsetUtil;

import system.Config;
import system.L;
import util.ChannelBufferUtil;

public class VerifyHandler91 extends VerifyHandler{
    @Override
    public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) {
    	if (client != null) {
    		notifyClient(true);
    	}
    	L.debug(e.getChannel().getRemoteAddress()  + " receipt close");
    }
    
    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
    	L.debug(e.getChannel().getRemoteAddress()  + " receipt connect");
        // Prepare the HTTP request.
    	String getParam = "?AppId="+Config.APP_ID_91 + "&Act=1&CooOrderSerial=" + receipt 
    			+ "&Sign=" + DigestUtils.md5Hex(Config.APP_ID_91 + "1" + receipt + Config.APP_KEY_91);
    	L.debug("request:" + Config.VERIFY_PATH + getParam);
        HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, Config.VERIFY_PATH + getParam);
        request.setHeader(HttpHeaders.Names.HOST, Config.VERIFY_HOST);
        request.setHeader(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE);
        // Send the HTTP request.
        e.getChannel().write(request);
    }
    
    public String HashToMD5Hex(String source) {
    	String result = "";
    	try {	 
    		byte[] bytes = source.getBytes("utf-8"); 
    		MessageDigest md5 = MessageDigest.getInstance("MD5"); 
    		md5.update(bytes);  
    		byte[] md5Byte = md5.digest();
    		if (md5Byte != null) {  
    			result = new String(HexBin.encode(md5Byte), "utf-8");
    		} 
    	} catch (NoSuchAlgorithmException e) { 
    		L.error("NoSuchAlgorithmException"); 
    	} catch (UnsupportedEncodingException e) { 
    		L.error("UnsupportedEncodingException");
    	} 
    	return result.toLowerCase();
    }
    
    public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
    	Channel channel = e.getChannel();
    	channel.close();
    	L.debug(e.getChannel().getRemoteAddress()  + " receipt disconnect");
    }

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
    	HttpResponse response = (HttpResponse) e.getMessage();
    	
    	L.debug("STATUS: " + response.getStatus());
    	L.debug("VERSION: " + response.getProtocolVersion());
    	
    	ChannelBuffer content = response.getContent();

    	if (content.readable()) {
    		String json = content.toString(CharsetUtil.UTF_8);
    		L.info("CONTENT {" + json + "} END OF CONTENT");
    		if (checkResult(json)) {
    			notifyClient(true);
    			db.addReceipt91(guid, receipt, uname, json);
    		} else {
    			notifyClient(false);
    		}
    	} else {
    		L.error("no check result");
    		notifyClient(true);
    	}
    }
    
    private boolean checkResult(String json) {
    	if (json.indexOf(Config.APP_ID_91) == -1) {
    		L.info("error product id");
    		return false;
    	}
    	if (json.indexOf("\"ErrorCode\":\"1\"") != -1)
    		return true;
    	if (json.indexOf("\"ErrorCode\": \"1\"") != -1)
    		return true;    	
    	return false;
    }
    
    private void notifyClient(boolean success) {
    	if (client != null && client.syner._channel.isConnected()) {
    		L.info("guid:" + guid + ", ip:" + client.syner._channel.getRemoteAddress()
    				+ ", purchase result: " + success);
    		ChannelBuffer buf = client.syner.prepareQueryResult();
    		ChannelBufferUtil.writeBool(buf, success);
    		client.syner.sendMsg(true);
    		client = null;	
    	}
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
    	try {
    		L.error(e.toString());
    		Throwable cause = e.getCause();
    		StackTraceElement[] trace; 
    		if (cause instanceof InvocationTargetException) {
    			InvocationTargetException ite = (InvocationTargetException)cause;
    			L.error(ite.getTargetException().toString());
    			trace = ite.getTargetException().getStackTrace();
    		} else {
    			trace = cause.getStackTrace();
    		}
    		
    		for (StackTraceElement st: trace) {
    			L.error(st.toString());
    		}
    	} catch (Exception ept) {
    		
    	} finally {
    		e.getChannel().close();
    	}
    }
}
